package cn.com.netty.zmynetty;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelId;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class NettyMessageHandler extends SimpleChannelInboundHandler<Object> {

    private static final Logger logger= LoggerFactory.getLogger(NettyMessageHandler.class);
    private static ChannelGroup GlobalGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    private static ConcurrentMap<String, ChannelId> ChannelMap = new ConcurrentHashMap();

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {

        if(msg instanceof FullHttpRequest) {
            // 以http请求形式接入,实际使用WebSocket方式
            logger.info("MyNetty Received first message: " + msg);
        } else if(msg instanceof WebSocketFrame) {
            // 处理 WebSocket客户端消息
            logger.info("MyNetty Received more message: " + msg);

            // 判断是否ping消息
            if (msg instanceof PingWebSocketFrame) {
                logger.info("---------ping---------");
            }
            // 本例程仅支持文本消息,不支持二进制消息
            if (!(msg instanceof TextWebSocketFrame)) {
                logger.info("MyNetty not support binary message.");
            }
            // 返回应答消息
            String request = ((TextWebSocketFrame) msg).text();
            TextWebSocketFrame tws = new TextWebSocketFrame("client id(" + ctx.channel().id() + ") " + request);
            // 群发消息
            GlobalGroup.writeAndFlush(tws);
        } else {
            logger.info("MyNetty Received message not match.");
        }
    }

    /**
     * 添加连接
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("MyNetty Client join in connection: " + ctx.channel());
        GlobalGroup.add(ctx.channel());
        ChannelMap.put(ctx.channel().id().asShortText(), ctx.channel().id());
    }

    /**
     * 断开连接
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        logger.info("MyNetty Client shuts connection: " + ctx.channel());
        GlobalGroup.remove(ctx.channel());
        ChannelMap.remove(ctx.channel().id().asShortText());
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    /**
     * 出现异常
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("MyNetty Error", cause);
    }
}
